home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4.md / machAsm.s < prev    next >
Text File  |  1991-03-29  |  39KB  |  1,397 lines

  1. /* machAsm.s --
  2.  *
  3.  *     Contains misc. assembler routines for the sun4.
  4.  *
  5.  * Copyright (C) 1985 Regents of the University of California
  6.  * All rights reserved.
  7.  *
  8.  * rcs = $Header: /sprite/src/kernel/mach/sun4.md/RCS/machAsm.s,v 9.14 91/03/29 17:58:03 shirriff Exp $ SPRITE (Berkeley)
  9.  */
  10.  
  11. #include "user/proc.h"
  12. #include "machConst.h"
  13. #include "machAsmDefs.h"
  14. .seg    "text"
  15.  
  16. /*
  17.  * ----------------------------------------------------------------------
  18.  *
  19.  * Mach_GetPC --
  20.  *
  21.  *    Jump back to caller, moving the return address that was put into
  22.  *    %RETURN_ADDR_REG as a side effect of the call into the %RETURN_VAL_REG.
  23.  *
  24.  * Results:
  25.  *    Old pc is returned in %RETURN_VAL_REG.
  26.  *
  27.  * Side effects:
  28.  *    None.
  29.  *
  30.  * ----------------------------------------------------------------------
  31.  */
  32. .globl    _Mach_GetPC
  33. _Mach_GetPC:
  34.     retl
  35.     mov    %RETURN_ADDR_REG, %RETURN_VAL_REG
  36.  
  37.  
  38. /*
  39.  * ----------------------------------------------------------------------
  40.  *
  41.  * Mach_GetCallerPC --
  42.  *
  43.  *    Return the PC of the caller of the routine who called us.
  44.  *
  45.  * Results:
  46.  *    Our caller's caller's pc.
  47.  *
  48.  * Side effects:
  49.  *    None.
  50.  *
  51.  * ----------------------------------------------------------------------
  52.  */
  53. .globl    _Mach_GetCallerPC
  54. _Mach_GetCallerPC:
  55.     retl
  56.     mov    %RETURN_ADDR_REG_CHILD, %RETURN_VAL_REG
  57.  
  58.  
  59. /*
  60.  *---------------------------------------------------------------------
  61.  *
  62.  * Mach_TestAndSet --
  63.  *
  64.  *     int Mach_TestAndSet(intPtr)
  65.  *          int *intPtr;
  66.  *
  67.  *     Test and set an operand.
  68.  *
  69.  * Results:
  70.  *     Returns 0 if *intPtr was zero and 1 if *intPtr was non-zero.  Also
  71.  *     in all cases *intPtr is set to a non-zero value.
  72.  *
  73.  * Side effects:
  74.  *     None.
  75.  *
  76.  *---------------------------------------------------------------------
  77.  */
  78. .globl    _Mach_TestAndSet
  79. _Mach_TestAndSet:
  80.     /*
  81.      * We're a leaf routine, so our return value goes in the save register
  82.      * that our operand does.  Move the operand before overwriting.
  83.      * The ISP description of the swap instruction indicates that it is
  84.      * okay to use the same address and destination registers.  This will
  85.      * put the address into the addressed location to set it.  That means
  86.      * we can't use address 0, but we shouldn't be doing that anyway.
  87.      */
  88. #ifdef SWAP_INSTR_WORKS
  89.     swap    [%RETURN_VAL_REG], %RETURN_VAL_REG    /* set addr with addr */
  90. #else
  91.     ldstub    [%RETURN_VAL_REG], %RETURN_VAL_REG    /* value into reg */
  92. #endif /* SWAP_INSTR_WORKS */
  93.     tst    %RETURN_VAL_REG                /* was it set? */
  94.     be,a    ReturnZero                /* if not, return 0 */
  95.     clr    %RETURN_VAL_REG                /* silly, delay slot */
  96.     mov    0x1, %RETURN_VAL_REG            /* yes set, return 1 */
  97. ReturnZero:
  98.     retl
  99.     nop
  100.  
  101.  
  102. /*
  103.  *---------------------------------------------------------------------
  104.  *
  105.  * Mach_GetMachineType -
  106.  *
  107.  *    Returns the type of machine that is stored in the id prom.
  108.  *
  109.  *    int    Mach_GetMachineType()
  110.  *
  111.  * Results:
  112.  *    The type of machine.
  113.  *
  114.  * Side effects:
  115.  *    None.
  116.  *
  117.  *---------------------------------------------------------------------
  118.  */
  119. .globl    _Mach_GetMachineType
  120. _Mach_GetMachineType:
  121.     set    VMMACH_MACH_TYPE_ADDR, %o0
  122. #ifdef sun4c
  123.     ldub    [%o0], %o0
  124. #else
  125.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  126. #endif
  127.     retl
  128.     nop
  129.  
  130.  
  131. /*
  132.  *---------------------------------------------------------------------
  133.  *
  134.  * Mach_GetEtherAddress -
  135.  *
  136.  *    Returns the type of machine that is stored in the id prom.
  137.  *
  138.  *    Net_EtherAddress *Mach_GetEtherAddress(ðerAddress)
  139.  *
  140.  * Results:
  141.  *    The argument struct gets the prom's ethernet address and is
  142.  *    returned.
  143.  *
  144.  * Side effects:
  145.  *    None.
  146.  *
  147.  *---------------------------------------------------------------------
  148.  */
  149. .globl    _Mach_GetEtherAddress
  150. _Mach_GetEtherAddress:
  151.     set    VMMACH_ETHER_ADDR, %OUT_TEMP1
  152.     /* first byte */
  153. #ifdef sun4c
  154.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  155. #else
  156.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  157. #endif
  158.     stb    %OUT_TEMP2, [%o0]
  159.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  160.     add    %o0, 1, %o0
  161.  
  162.     /* second byte */
  163. #ifdef sun4c
  164.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  165. #else
  166.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  167. #endif
  168.     stb    %OUT_TEMP2, [%o0]
  169.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  170.     add    %o0, 1, %o0
  171.  
  172.     /* third byte */
  173. #ifdef sun4c
  174.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  175. #else
  176.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  177. #endif
  178.     stb    %OUT_TEMP2, [%o0]
  179.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  180.     add    %o0, 1, %o0
  181.  
  182.     /* fourth byte */
  183. #ifdef sun4c
  184.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  185. #else
  186.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  187. #endif
  188.     stb    %OUT_TEMP2, [%o0]
  189.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  190.     add    %o0, 1, %o0
  191.  
  192.     /* fifth byte */
  193. #ifdef sun4c
  194.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  195. #else
  196.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  197. #endif
  198.     stb    %OUT_TEMP2, [%o0]
  199.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  200.     add    %o0, 1, %o0
  201.  
  202.     /* sixth byte */
  203. #ifdef sun4c
  204.     ldub    [%OUT_TEMP1], %OUT_TEMP2
  205. #else
  206.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  207. #endif
  208.     stb    %OUT_TEMP2, [%o0]
  209.     sub    %o0, 5, %o0        /* restore pointer parameter */
  210.  
  211.     retl
  212.     nop
  213.  
  214. /*
  215.  *---------------------------------------------------------------------
  216.  *
  217.  * Mach_MonTrap -
  218.  *
  219.  *      Trap to the monitor.  This involves dummying up a trap stack for the
  220.  *      monitor, allowing non-maskable interrupts and then jumping to the
  221.  *      monitor trap routine.  When it returns, non-maskable interrupts are
  222.  *      disabled and we return.
  223.  *
  224.  *    void    Mach_MonTrap(address_to_trap_to)
  225.  *
  226.  * Results:
  227.  *      None.
  228.  *
  229.  * Side effects:
  230.  *      None.
  231.  *
  232.  * --------------------------------------------------------------------
  233.  */
  234. .global    _Mach_MonTrap
  235. _Mach_MonTrap:
  236.     save    %sp, -MACH_SAVED_STATE_FRAME, %sp
  237.     /* enable non-maskable interrupts? */
  238.     /* get address */
  239.     call    %i0
  240.     nop
  241.     /* disable non-maskable interrupts? */
  242.     ret
  243.     restore
  244.  
  245.  
  246. /*
  247.  *---------------------------------------------------------------------
  248.  *
  249.  * Mach_ContextSwitch -
  250.  *
  251.  *    Mach_ContextSwitch(fromProcPtr, toProcPtr)
  252.  *
  253.  *    Switch the thread of execution to a new process.  This routine
  254.  *    is passed a pointer to the process to switch from and a pointer to
  255.  *    the process to switch to.  It goes through the following steps:
  256.  *
  257.  *    1) Change to the new context.
  258.  *    2) save stuff
  259.  *    3) restore stuff
  260.  *    4) Return in the new process
  261.  *
  262.  *    The kernel stack is changed implicitly when the registers are restored.
  263.  *
  264.  * Results:
  265.  *    None.
  266.  *
  267.  * Side effects:
  268.  *    The kernel stack, all general registers, and some special-purpose
  269.  *    registers are changed.
  270.  *
  271.  *---------------------------------------------------------------------
  272.  */
  273. .globl    _Mach_ContextSwitch
  274. _Mach_ContextSwitch:
  275.     /*
  276.      * We call stuff here, so we need a new window.  An overflow trap
  277.      * is okay here.  Save enough space for the context switch state on
  278.      * the stack.
  279.      */
  280.     save     %sp, -MACH_SAVED_STATE_FRAME, %sp
  281.     mov    %psr, %CUR_PSR_REG
  282.  
  283.     /*
  284.      * Enable the floating point processor so we can save and
  285.      * restore FPU state if necessary.
  286.      */
  287.     set    MACH_ENABLE_FPP, %VOL_TEMP1
  288.     or    %CUR_PSR_REG,%VOL_TEMP1,%VOL_TEMP1
  289.     mov    %VOL_TEMP1, %psr
  290.     /*
  291.      * No delay instructions needed here as long as the following
  292.      * three instructions don't touch the FPU.
  293.      *
  294.      * Save stack pointer into state struct.  This is also the pointer
  295.      * in the mach state struct of the saved context switch state.  It
  296.      * just so happens it's stored on the stack...
  297.      */
  298.     set    _machStatePtrOffset, %VOL_TEMP1
  299.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* get offset */
  300.         /* FPU is now active. */
  301.     add    %i0, %VOL_TEMP1 , %VOL_TEMP1        /* add to base */
  302.     ld    [%VOL_TEMP1], %SAFE_TEMP        /* get machStatePtr */
  303.     add    %SAFE_TEMP, MACH_SWITCH_REGS_OFFSET, %VOL_TEMP1
  304.     st    %sp, [%VOL_TEMP1]
  305.  
  306.     /*
  307.      * If FPU is active for this process, save FPU state.
  308.      */
  309.     ld    [%SAFE_TEMP+MACH_FPU_STATUS_OFFSET], %VOL_TEMP1
  310.     tst    %VOL_TEMP1
  311.     bz    noFPUactive
  312.     /*
  313.      *  Note: Part of following set instruction executed in "bz" delay
  314.      *  slot.  This trashes %VOL_TEMP1 when the branch is taken.
  315.      *  
  316.      *  We are saving the user's FPU state into the trap regs during
  317.      *  the context switch because we don't want the latency of saving
  318.      *  all the floating point state on every trap.  This works because
  319.      *  the kernel doesn't user floating point instructions.  
  320.      *
  321.      *  Tricky code - We save the fromProcPtr in _machFPUSaveProcPtr and
  322.      *  execute a "st %fsr". The "st fsr" will pause until all FPU ops
  323.      *  are compete.  If any FPU execptions are pending we will get a
  324.      *  FP_EXCEPTION trap on the instruction marked by the label 
  325.      *  _machFPUSyncInst. The routine MachHandleTrap in
  326.      *  machCode.c will catch this fault and note it in the processes
  327.      *  PCB.  
  328.      */
  329.     set    _machFPUSaveProcPtr, %VOL_TEMP1
  330.     st    %i0, [%VOL_TEMP1];
  331.     /*
  332.      * Set %SAFE_TEMP to be trapRegsPtr.
  333.      */
  334.     ld    [%SAFE_TEMP + MACH_TRAP_REGS_OFFSET], %SAFE_TEMP
  335. .global _machFPUSyncInst
  336. _machFPUSyncInst: st    %fsr, [%SAFE_TEMP + MACH_FPU_FSR_OFFSET]
  337.         /*
  338.      * The following symbol is include to make the following code 
  339.      * be attributed to the routine Mach_ContextSwitch2 and not
  340.      * _machFPUSyncInst.
  341.      */
  342. .globl    Mach_ContextSwitch2
  343. Mach_ContextSwitch2:
  344.     std %f0, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*0]
  345.     std %f2, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*2]
  346.     std %f4, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*4]
  347.     std %f6, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*6]
  348.     std %f8, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*8]
  349.     std %f10, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*10]
  350.     std %f12, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*12]
  351.     std %f14, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*14]
  352.     std %f16, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*16]
  353.     std %f18, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*18]
  354.     std %f20, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*20]
  355.     std %f22, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*22]
  356.     std %f24, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*24]
  357.     std %f26, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*26]
  358.     std %f28, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*28]
  359.     std %f30, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*30]
  360. noFPUactive:
  361.     /*
  362.      * Save context switch state, globals only for the time being...
  363.      * This gets saved in our stack frame.
  364.      */
  365.     MACH_SAVE_GLOBAL_STATE()
  366.  
  367.     /*
  368.      * Now make sure all windows are flushed to the stack.  We do this
  369.      * with MACH_NUM_WINDOWS - 1 saves and restores.  The window overflow
  370.      * and underflow traps will then handle this for us.  We put the counter
  371.      * in a global, since they have all been saved already and are free
  372.      * for our use and we need the value across windows.
  373.      */
  374.     set    (MACH_NUM_WINDOWS - 1), %g1
  375. ContextSaveSomeMore:
  376.     save
  377.     subcc    %g1, 1, %g1
  378.     bne    ContextSaveSomeMore
  379.     nop
  380.     set    (MACH_NUM_WINDOWS - 1), %g1
  381. ContextRestoreSomeMore:
  382.     restore
  383.     subcc    %g1, 1, %g1
  384.     bne    ContextRestoreSomeMore
  385.     nop
  386.  
  387.     /*
  388.      * Switch contexts to that of toProcPtr.  It's the second arg, so
  389.      * move it to be first arg of routine we call.
  390.      */
  391.     mov    %i1, %o0
  392.     call    _VmMach_SetupContext, 1
  393.     nop
  394.     /*
  395.      * Context to use was returned in %RETURN_VAL_REG.  Set the context
  396.      * to that value.  VmMachSetContextReg is a leaf routine, so we
  397.      * leave the value for its argument in %RETURN_VAL_REG.
  398.      */
  399.     call    _VmMachSetContextReg, 1
  400.     nop
  401.  
  402.     /*
  403.      * Restore stack pointer of new process - WE SWITCH STACKS HERE!!!
  404.      * the pointer to the new processes' state structure goes into
  405.      * %SAFE_TEMP.
  406.      */
  407.     set    _machStatePtrOffset, %VOL_TEMP1
  408.     ld    [%VOL_TEMP1], %VOL_TEMP1    /* get offset */
  409.     add    %i1, %VOL_TEMP1, %VOL_TEMP1    /* &(procPtr->machStatePtr) */
  410.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* procPtr->machStatePtr */
  411.     add    %SAFE_TEMP, MACH_SWITCH_REGS_OFFSET, %VOL_TEMP1
  412.     ld    [%VOL_TEMP1], %sp
  413.  
  414.     /* Update machCurStatePtr */
  415.     set    _machCurStatePtr, %VOL_TEMP1
  416.     st    %SAFE_TEMP, [%VOL_TEMP1]
  417.     /*
  418.      * If FPU is active for this process, restore the FPU state.
  419.      */
  420.     ld    [%SAFE_TEMP+MACH_FPU_STATUS_OFFSET], %VOL_TEMP1
  421.     tst    %VOL_TEMP1
  422.     bz    dontRestoreFPU
  423.     nop
  424.     /*
  425.      * Set %SAFE_TEMP to be machStatePtr.
  426.      */
  427.     ld  [%SAFE_TEMP + MACH_TRAP_REGS_OFFSET], %SAFE_TEMP
  428.     ld  [%SAFE_TEMP + MACH_FPU_FSR_OFFSET], %fsr
  429.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*0],%f0
  430.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*2],%f2 
  431.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*4],%f4 
  432.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*6],%f6 
  433.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*8],%f8 
  434.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*10],%f10
  435.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*12],%f12
  436.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*14],%f14 
  437.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*16],%f16 
  438.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*18],%f18 
  439.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*20],%f20 
  440.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*22],%f22
  441.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*24],%f24 
  442.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*26],%f26
  443.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*28],%f28
  444.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*30],%f30
  445. dontRestoreFPU:
  446.  
  447.     /* restore global registers of new process */
  448.     MACH_RESTORE_GLOBAL_STATE()
  449.  
  450.     /*
  451.      * Restore the local and in registers for this process.  (We need
  452.      * at least the psr in %CUR_PSR_REG and the fp and return pc.)
  453.      * To do this we set the wim to this window and do a save and restore.
  454.      * That way the registers are automatically saved from the stack.
  455.      * We could instead save all these explicitly in the state structure
  456.      * and not do a save and restore, but that wouldn't save that many
  457.      * loads and it also would be different than how we save and restore
  458.      * with the debugger.  It's nice to have them the same.
  459.      */
  460.     MACH_SET_WIM_TO_CWP()
  461.     save
  462.     restore
  463.     /* restore user stack pointer if a user process? */
  464.  
  465.     /*
  466.      * Restore status register in such a way that it doesn't make
  467.      * us change windows.
  468.      */
  469.     MACH_RESTORE_PSR()
  470.     ret
  471.     restore
  472.  
  473. /*
  474.  *---------------------------------------------------------------------
  475.  *
  476.  * MachRunUserProc -
  477.  *
  478.  *    void    MachRunUserProc()
  479.  *
  480.  *    Make the first user process start off by returning it from a kernel
  481.  *    trap.
  482.  *    Interrupts must be disabled coming into this.
  483.  *
  484.  *    MachRunUserProc();
  485.  *
  486.  * Results:
  487.  *    Restore registers and return to user space.
  488.  *
  489.  * Side effects:
  490.  *    Registers restored.
  491.  *
  492.  *---------------------------------------------------------------------
  493.  */
  494. .globl    _MachRunUserProc
  495. _MachRunUserProc:
  496.     /*
  497.      * Get values to restore registers to from the state structure.
  498.      * We set up %VOL_TEMP2 to point to trapRegs structure and restore
  499.      * from there.
  500.      */
  501.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  502.     set    _machCurStatePtr, %VOL_TEMP2
  503.     st    %VOL_TEMP1, [%VOL_TEMP2]
  504.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  505.     ld    [%VOL_TEMP1], %VOL_TEMP2    /* machStatePtr->trapRegs */
  506.     mov    %VOL_TEMP2, %sp            /* set sp to trapRegs */
  507.     /*
  508.      * Restore %fp.  This will be the user's %sp when we return from
  509.      * the trap window.
  510.      */
  511.     add    %VOL_TEMP2, MACH_FP_OFFSET, %VOL_TEMP1
  512.     ld    [%VOL_TEMP1], %fp        /* set %fp - user sp */
  513.     andcc    %fp, 0x7, %g0
  514.     be    UserStackOkay
  515.     nop
  516.     /*
  517.      * User stack wasn't aligned.  It should have been when it got here!
  518.      */
  519.     set    _MachRunUserDeathString, %o0
  520.     call    _printf, 1
  521.     nop
  522.     set    PROC_TERM_DESTROYED, %o0
  523.     set    PROC_BAD_STACK, %o1
  524.     clr    %o2
  525.     set    _Proc_ExitInt, %VOL_TEMP1
  526.     call    %VOL_TEMP1, 3
  527.     nop
  528. UserStackOkay:
  529.     /*
  530.      * Set return from trap pc and next pc.
  531.      */
  532.     add    %VOL_TEMP2, MACH_TRAP_PC_OFFSET, %VOL_TEMP1
  533.     ld    [%VOL_TEMP1], %CUR_PC_REG
  534.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  535.     ld    [%VOL_TEMP1], %NEXT_PC_REG
  536.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  537.     ld    [%VOL_TEMP1], %CUR_TBR_REG
  538.  
  539.     /*
  540.      * Put a return value into the return value register.
  541.      */
  542.     add    %VOL_TEMP2, MACH_ARG0_OFFSET, %VOL_TEMP1
  543.     ld    [%VOL_TEMP1], %i0
  544.     /*
  545.      * Restore the other in registers, which were trapper's out regs.
  546.      * We've already restored fp = i6, so skip it.
  547.      */
  548.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  549.     ld    [%VOL_TEMP1], %i1
  550.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  551.     ld    [%VOL_TEMP1], %i2
  552.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  553.     ld    [%VOL_TEMP1], %i3
  554.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  555.     ld    [%VOL_TEMP1], %i4
  556.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  557.     ld    [%VOL_TEMP1], %i5
  558.  
  559.     add    %VOL_TEMP1, 8, %VOL_TEMP1
  560.     ld    [%VOL_TEMP1], %i7
  561.     /*
  562.      * Get new psr value.
  563.      */
  564.     add    %VOL_TEMP2, MACH_PSR_OFFSET, %VOL_TEMP1
  565.     ld    [%VOL_TEMP1], %CUR_PSR_REG
  566.  
  567.     /*
  568.      * Now go through regular return from trap code.
  569.      * We must make sure that the window we will return to from the trap
  570.      * is invalid when we get into MachReturnFromTrap so that it will
  571.      * be restored from the user stack.  Otherwise the in registers (such
  572.      * as frame pointer) in that window we return to will be bad and
  573.      * won't be restored correctly.
  574.      */
  575.     MACH_SET_WIM_TO_CWP();
  576.     MACH_RETREAT_WIM(%VOL_TEMP1, %VOL_TEMP2, SetWimForChild);
  577.  
  578.     set    _MachReturnFromTrap, %VOL_TEMP1
  579.     jmp    %VOL_TEMP1
  580.     nop
  581.  
  582. /*
  583.  *---------------------------------------------------------------------
  584.  *
  585.  * MachGetCurrentSp -
  586.  *
  587.  *    Address    MachGetCurrentSp()
  588.  *
  589.  *    Return the value of the current stack pointer.
  590.  *
  591.  * Results:
  592.  *    The current stack pointer.
  593.  *
  594.  * Side effects:
  595.  *    None.
  596.  *
  597.  *---------------------------------------------------------------------
  598.  */
  599. .globl    _MachGetCurrentSp
  600. _MachGetCurrentSp:
  601.     mov    %sp, %o0
  602.     retl
  603.     nop
  604.  
  605.  
  606. /*
  607.  *---------------------------------------------------------------------
  608.  *
  609.  * MachHandleSignal -
  610.  *
  611.  *    void MachHandleSignal()
  612.  *
  613.  *    Setup the necessary stack to handle a signal.  Interrupts are off when
  614.  *    we enter.  They must be off so we don't overwrite the signal stuff
  615.  *    in the process state with more signal stuff.
  616.  *
  617.  * Results:
  618.  *    We return via a rett to user mode to the pc of the signal handler.
  619.  *
  620.  * Side effects:
  621.  *    Depends on signal handler, etc.
  622.  *
  623.  *---------------------------------------------------------------------
  624.  */
  625. .globl    _MachHandleSignal
  626. _MachHandleSignal:
  627.     /*
  628.      * Save window to stack so that user trap values will be saved
  629.      * to kernel stack so that when we copy them to the user stack, we'll
  630.      * get the correct values.
  631.      */
  632.     MACH_SAVE_WINDOW_TO_STACK()
  633.  
  634.     /* Get new user stack pointer value into %SAFE_TEMP */
  635.     set    _machSignalStackSizeOnStack, %VOL_TEMP1
  636.     ld    [%VOL_TEMP1], %VOL_TEMP1    /* size MachSignalStack */
  637.     sub    %fp, %VOL_TEMP1, %SAFE_TEMP        /* new sp in safetemp */
  638.  
  639.     /* Copy out sig stack from state structure to user stack */
  640.     set    _machSigStackOffsetOnStack, %VOL_TEMP1
  641.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* offset Sig_Stack */
  642.     add    %SAFE_TEMP, %VOL_TEMP1, %o2    /* dest addr of Sig_Stack */
  643.     set    _machSigStackSize, %o0
  644.     ld    [%o0], %o0                /* size of Sig_Stack */
  645.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  646.     set    _machSigStackOffsetInMach, %VOL_TEMP2
  647.     ld    [%VOL_TEMP2], %VOL_TEMP2
  648.     add    %VOL_TEMP1, %VOL_TEMP2, %o1    /* src addr of sig stack */
  649.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  650.     call    _Vm_CopyOut, 3                /* copy Sig_Stack */
  651.     nop
  652.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  653.     be    CopiedOutSigStack
  654.     nop
  655. CopyOutForSigFailed:
  656.     /*
  657.      * Copying to user stack failed.  We have no choice but to kill the
  658.      * thing.  This causes us to exit this routine and process.
  659.      */
  660.     set    _MachHandleSignalDeathString, %o0
  661.     call    _printf, 1
  662.     nop
  663.     set    PROC_TERM_DESTROYED, %o0
  664.     set    PROC_BAD_STACK, %o1
  665.     clr    %o2
  666.     call    _Proc_ExitInt, 3
  667.     nop
  668.  
  669. CopiedOutSigStack:
  670.     /* Copy out sig context from state structure to user stack */
  671.     /* put addr of mach state structure in %VOL_TEMP1 again */
  672.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  673.     set    _machSigContextOffsetOnStack, %VOL_TEMP2
  674.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset Sig_Context */
  675.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* dest addr of Sig_Context */
  676.     set    _machSigContextSize, %o0
  677.     ld    [%o0], %o0            /* size of Sig_Context */
  678.     set    _machSigContextOffsetInMach, %VOL_TEMP2
  679.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset Sig_Context */
  680.     add    %VOL_TEMP1, %VOL_TEMP2, %o1    /* src addr of sig context */
  681.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  682.     call    _Vm_CopyOut, 3                /* copy Sig_Context */
  683.     nop
  684.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  685.     bne    CopyOutForSigFailed
  686.     nop
  687.  
  688.     /* Copy out user trap state from state structure to user stack */
  689.     /* put addr of mach state structure in %VOL_TEMP1 again */
  690.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  691.     set    _machSigUserStateOffsetOnStack, %VOL_TEMP2
  692.     ld    [%VOL_TEMP2], %VOL_TEMP2
  693.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* dest addr of user state */
  694.     set    MACH_SAVED_STATE_FRAME, %o0    /* size of copy */
  695.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  696.     ld    [%VOL_TEMP1], %o1        /* address of trap regs */
  697.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  698.     call    _Vm_CopyOut, 3
  699.     nop
  700.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  701.     bne    CopyOutForSigFailed
  702.     nop
  703.  
  704.     /*
  705.      * Get address of trapInst field in machContext field of sig context
  706.      * and put it in ret addr of next window so when we return from handler
  707.      * in next window, we'll return to the trap instruction.
  708.      */
  709.     set    _machSigTrapInstOffsetOnStack, %VOL_TEMP2
  710.     ld    [%VOL_TEMP2], %VOL_TEMP2    /* offset to trap instr */
  711.     add    %SAFE_TEMP, %VOL_TEMP2, %RETURN_ADDR_REG    /* addr */
  712.     /* ret from proc instr jumps to (ret addr + 8), so subtract 8 here */
  713.     sub    %RETURN_ADDR_REG, 0x8, %RETURN_ADDR_REG
  714.  
  715.     /*
  716.      * Set return from trap pc and next pc in the next window to the
  717.      * address of the handler so that when we do a rett back to this
  718.      * window from the next window, we'll start executing at the signal
  719.      * handler.  This requires a global register to get
  720.      * it across the window boundary, so we must do this before restoring
  721.      * our global registers.  This should be done after the Vm_CopyOut's
  722.      * so that there's no overwriting our confusion with the registers
  723.      * in the next window.
  724.      */
  725.     set    _machSigPCOffsetOnStack, %VOL_TEMP1
  726.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* offset to pc field */
  727.     add    %SAFE_TEMP, %VOL_TEMP1, %VOL_TEMP1    /* addr of sig pc */
  728.     ld    [%VOL_TEMP1], %g3
  729.     
  730.     save
  731.     mov    %g3, %CUR_PC_REG        /* trap pc addr into rett pc */
  732.     add    %g3, 0x4, %NEXT_PC_REG
  733.     restore
  734.  
  735.     /*
  736.      * restore global regs for user after calling Vm_CopyOut and after
  737.      * using %g3 (above) and before messing up our kernel stack pointer.
  738.      */
  739.     MACH_RESTORE_GLOBAL_STATE()
  740.  
  741.     /*
  742.      * Set up our out registers to be correct arguments to sig handler,
  743.      * since this is the window it will start off in, but the C code will
  744.      * do a save into the next window so our out's will be the handler's
  745.      * in regs.
  746.      *
  747.      *    Handler(sigNum, sigCode, contextPtr, sigAddr)
  748.      */
  749.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  750.     set    _machSigStackOffsetInMach, %VOL_TEMP2
  751.     ld    [%VOL_TEMP2], %VOL_TEMP2    /* offset to sig stack */
  752.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP2    /* addr of sig stack */
  753.     set    _machSigNumOffsetInSig, %o0
  754.     ld    [%o0], %o0            /* offset to sigNum */
  755.     add    %o0, %VOL_TEMP2, %o0        /* addr of sig num */
  756.     ld    [%o0], %o0            /* sig num == arg 1 */
  757.     set    _machSigCodeOffsetInSig, %o1
  758.     ld    [%o1], %o1            /* offset to sigCode */
  759.     add    %o1, %VOL_TEMP2, %o1        /* addr of sig code */
  760.     ld    [%o1], %o1            /* sig code == arg2 */
  761.     /* Stack address of Sig_Context is third arg */
  762.     set    _machSigContextOffsetOnStack, %VOL_TEMP2
  763.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset Sig_Context */
  764.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* stack addr context = arg3  */
  765.     set    _machSigStackOffsetInMach, %VOL_TEMP2
  766.     ld    [%VOL_TEMP2], %VOL_TEMP2    /* offset to sig stack */
  767.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP2    /* addr of sig stack */
  768.     set    _machSigAddrOffsetInSig, %o3
  769.     ld    [%o3], %o3            /* offset to sigAddr */
  770.     add    %o3, %VOL_TEMP2, %o3        /* addr of sig addr */
  771.     ld    [%o3], %o3            /* sig addr == arg 4 */
  772.  
  773.     /*
  774.      * NOTE: the sigStack.sigContextPtr field has not been filled in.
  775.      * Will that matter?
  776.      */
  777.  
  778.     /* set stack pointer in this window to new user stack pointer */
  779.     mov    %SAFE_TEMP, %sp
  780.  
  781.     /*
  782.      * Move the user psr to restore to next window, since we'll have
  783.      * to restore it from there since it disables traps and we must still
  784.      * have traps enabled when executing the save instruction, in case
  785.      * of window overflow.
  786.      */
  787.     mov    %CUR_PSR_REG, %o4
  788.  
  789.     /*
  790.      * Move to window to do rett from.  We must do this while traps are
  791.      * still enabled, in case we get overflow.
  792.      */
  793.     save
  794.  
  795.     /*
  796.      * Set up psr for return to user mode.  It must be the user mode
  797.      * psr with traps disabled.
  798.      */
  799.     mov    %i4, %CUR_PSR_REG        /* so restore psr will work */
  800.     MACH_RESTORE_PSR()
  801.  
  802.     jmp    %CUR_PC_REG
  803.     rett    %NEXT_PC_REG
  804.  
  805. /*
  806.  *---------------------------------------------------------------------
  807.  *
  808.  * MachReturnFromSignal -
  809.  *
  810.  *    void MachReturnFromSignal()
  811.  *
  812.  *    The routine executed after a return from signal trap.  This must
  813.  *    restore state from the user stack so we can return to user mode
  814.  *    via the regular return from trap method.
  815.  *
  816.  *    Interrupts must be off when we're called.
  817.  *
  818.  * Results:
  819.  *    We execute the return-from-trap code, so it depends what happens there.
  820.  *
  821.  * Side effects:
  822.  *    Depends.
  823.  *
  824.  *---------------------------------------------------------------------
  825.  */
  826. .globl    _MachReturnFromSignal
  827. _MachReturnFromSignal:
  828.     /*
  829.      * We've trapped into this window so our %fp is the user's sp that
  830.      * we set up before handling the signal.  We must copy stuff back off
  831.      * the user's stack to the trap regs to restore state.  But we're one
  832.      * window away from where we want to be, so we have to back up also.
  833.      */
  834.     /* get our kernel stack pointer into global regs (which get restored
  835.      * in MachReturnFromTrap) so we can keep it across windows.
  836.      */
  837.     mov    %sp, %g3
  838.     restore        /* no underflow since we just came from here */
  839.     /*
  840.      * I could at this point just move %sp to %SAFE_TEMP if I really
  841.      * trusted that %fp - sizeof (MachSignalStack) really equals %sp which
  842.      * was user sp we set up before calling signal handler, but I
  843.      * check this for now.
  844.      */
  845.     set    _machSignalStackSizeOnStack, %VOL_TEMP1
  846.     ld    [%VOL_TEMP1], %VOL_TEMP1    /* size MachSignalStack */
  847.     sub    %fp, %VOL_TEMP1, %SAFE_TEMP    /* sig user sp in safetemp */
  848.     cmp    %SAFE_TEMP, %sp
  849.     bne    CopyInForSigFailed
  850.     nop
  851.  
  852.     mov    %g3, %sp            /* kernel sp now here too */
  853.  
  854.     /* Copy in sig stack from user stack to mach state structure */
  855.     set    _machSigStackOffsetOnStack, %VOL_TEMP1
  856.     ld    [%VOL_TEMP1], %VOL_TEMP1    /* offset of Sig_Stack */
  857.     add    %SAFE_TEMP, %VOL_TEMP1, %o1    /* src addr of Sig_Stack */
  858.     set    _machSigStackSize, %o0
  859.     ld    [%o0], %o0            /* size of Sig_Stack */
  860.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  861.     set    _machSigStackOffsetInMach, %VOL_TEMP2
  862.     ld    [%VOL_TEMP2], %VOL_TEMP2
  863.     add    %VOL_TEMP1, %VOL_TEMP2, %o2    /* dest addr of sig stack */
  864.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  865.     call    _Vm_CopyIn, 3            /* copy Sig_Stack */
  866.     nop
  867.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  868.     be    CopiedInSigStack
  869.     nop
  870. CopyInForSigFailed:
  871.      /* Copy failed from user space - kill the process */ 
  872.     set    _MachReturnFromSignalDeathString, %o0
  873.     call    _printf, 1
  874.     nop
  875.     set    PROC_TERM_DESTROYED, %o0
  876.     set    PROC_BAD_STACK, %o1
  877.     clr    %o2
  878.     call    _Proc_ExitInt, 3
  879.     nop
  880.  
  881. CopiedInSigStack:
  882.     /* Copy in sig context from user stack to state structure */
  883.     /* put addr of mach state structure in %VOL_TEMP1 again */
  884.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  885.     set    _machSigContextOffsetOnStack, %VOL_TEMP2
  886.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset Sig_Context */
  887.     add    %SAFE_TEMP, %VOL_TEMP2, %o1    /* src addr of Sig_Context */
  888.     set    _machSigContextSize, %o0
  889.     ld    [%o0], %o0            /* size of Sig_Context */
  890.     set    _machSigContextOffsetInMach, %VOL_TEMP2
  891.     ld    [%VOL_TEMP2], %VOL_TEMP2    /* offset of Sig_Context */
  892.     add    %VOL_TEMP1, %VOL_TEMP2, %o2    /* dest addr of sig context */
  893.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  894.     call    _Vm_CopyIn, 3            /* copy Sig_Context */
  895.     nop
  896.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  897.     bne    CopyInForSigFailed
  898.     nop
  899.  
  900.     /*
  901.      * Call a routine that calls Sig_Return with appropriate stuff.
  902.      * This occurs after copying in the Sig stuff, above, because Sig_Return
  903.      * needs the Sig stuff.
  904.      */
  905.     call    _MachCallSigReturn
  906.     nop
  907.  
  908.     /* Copy in user trap state from user stack to kernel trap regs */
  909.     set    _machSigUserStateOffsetOnStack, %VOL_TEMP2
  910.     ld    [%VOL_TEMP2], %VOL_TEMP2
  911.     add    %SAFE_TEMP, %VOL_TEMP2, %o1        /* src addr of copy */
  912.     set    MACH_SAVED_STATE_FRAME, %o0        /* size of copy */
  913.     /* destination of copy is trapRegs, but our sp points to that already */
  914.     /* SHOULD I VERIFY THIS? */
  915.     mov    %sp, %o2                /* dest addr of copy */
  916.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  917.     call    _Vm_CopyIn, 3
  918.     nop
  919.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  920.     bne    CopyInForSigFailed
  921.     nop
  922.  
  923.     /* Restore user trap state */
  924.     mov    %sp, %g3            /* save stack pointer */
  925.     MACH_RESTORE_WINDOW_FROM_STACK()
  926.     /* test if stack pointer is the same */
  927.     cmp    %g3, %sp
  928.     mov    %g3, %sp        /* restore, in case it was bad */
  929.     bne    CopyInForSigFailed
  930.     nop
  931.  
  932.     /* Make sure the psr is okay since we got it from the user */
  933.     set    ~(MACH_PS_BIT), %VOL_TEMP1
  934.     and    %CUR_PSR_REG, %VOL_TEMP1, %CUR_PSR_REG    /* clear ps bit */
  935.     set    MACH_DISABLE_TRAP_BIT, %VOL_TEMP1
  936.     and    %CUR_PSR_REG, %VOL_TEMP1, %CUR_PSR_REG    /* clear trap en. bit */
  937.  
  938.     /*
  939.      * Now go through the regular return from trap code.
  940.      */
  941.     call    _MachReturnFromTrap
  942.     nop
  943.  
  944.  
  945. #ifdef NOTDEF
  946. /*
  947.  *---------------------------------------------------------------------
  948.  *
  949.  * MachFlushWindowsToStack -
  950.  *
  951.  *    void MachFlushWindowsToStack()
  952.  *
  953.  *    Flush all the register windows to the stack.
  954.  *     Interrupts must be off when we're called.
  955.  *
  956.  * Results:
  957.  *    None.
  958.  *
  959.  * Side effects:
  960.  *    None.
  961.  *
  962.  *---------------------------------------------------------------------
  963.  */
  964. .globl    _MachFlushWindowsToStack
  965. _MachFlushWindowsToStack:
  966.     mov    %g3, %o0
  967.     set    (MACH_NUM_WINDOWS - 1), %g3
  968. SaveTheWindow:
  969.     save
  970.     subcc    %g3, 1, %g3
  971.     bne    SaveTheWindow
  972.     nop
  973.     set    (MACH_NUM_WINDOWS - 1), %g3
  974. RestoreTheWindow:
  975.     restore
  976.     subcc    %g3, 1, %g3
  977.     bne    RestoreTheWindow
  978.     nop
  979.  
  980.     mov    %o0, %g3
  981.  
  982.     retl
  983.     nop
  984. #endif NOTDEF
  985.  
  986.  
  987. /*
  988.  *---------------------------------------------------------------------
  989.  *
  990.  * Mach_ReadPsr -
  991.  *
  992.  *    Capture %psr for C routines.
  993.  *
  994.  * Results:
  995.  *    %psr.
  996.  *
  997.  * Side effects:
  998.  *    None.
  999.  *
  1000.  *---------------------------------------------------------------------
  1001.  */
  1002. .globl    _Mach_ReadPsr
  1003. _Mach_ReadPsr:
  1004.     mov    %psr, %o0
  1005.     retl
  1006.     nop
  1007.  
  1008. #ifdef sun4c
  1009. .globl    _MachGetSyncErrorReg
  1010. _MachGetSyncErrorReg:
  1011.     set    VMMACH_SYNC_ERROR_REG, %o0
  1012.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1013.     retl
  1014.     nop
  1015.  
  1016. .globl    _MachGetASyncErrorReg
  1017. _MachGetASyncErrorReg:
  1018.     set    VMMACH_ASYNC_ERROR_REG, %o0
  1019.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1020.     retl
  1021.     nop
  1022.  
  1023. .globl    _MachGetSyncErrorAddrReg
  1024. _MachGetSyncErrorAddrReg:
  1025.     set    VMMACH_SYNC_ERROR_ADDR_REG, %o0
  1026.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1027.     retl
  1028.     nop
  1029.  
  1030. .globl    _MachGetASyncErrorAddrReg
  1031. _MachGetASyncErrorAddrReg:
  1032.     set    VMMACH_ASYNC_ERROR_ADDR_REG, %o0
  1033.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1034.     retl
  1035.     nop
  1036.  
  1037. .globl    _MachGetSystemEnableReg
  1038. _MachGetSystemEnableReg:
  1039.     set    VMMACH_SYSTEM_ENABLE_REG, %o0
  1040.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  1041.     retl
  1042.     nop
  1043. #endif
  1044.  
  1045. /*
  1046.  *---------------------------------------------------------------------
  1047.  *
  1048.  * MachHandleBadArgs -
  1049.  *
  1050.  *    A page fault occured in a copy-in or copy-out from a user-mode process,
  1051.  *    and the page couldn't be paged in.  So we want to return
  1052.  *    SYS_ARG_NOACCESS to the process from its system call.
  1053.  *    This means we must return this value from the routine doing the copying.
  1054.  *
  1055.  * Results:
  1056.  *    SYS_ARG_NOACCESS returned to process as if returned from its system
  1057.  *    call.
  1058.  *
  1059.  * Side effects:
  1060.  *    We cause the routine that was copying args to return SYS_ARG_NO_ACCESS.
  1061.  *
  1062.  *---------------------------------------------------------------------
  1063.  */
  1064. .globl    _MachHandleBadArgs
  1065. _MachHandleBadArgs:
  1066.     restore            /* back to page fault trap window */
  1067.     mov    %CUR_PSR_REG, %i1
  1068.     restore            /* back to copy routine that got trap */
  1069.     /* Copy routine was leaf routine and so return failure in %o0 */
  1070.     set    SYS_ARG_NOACCESS, %o0
  1071.     /* Set interrupts to what they were when trap occured. */
  1072.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1073.     retl            /* return from leaf routine */
  1074.     nop
  1075.  
  1076. /*
  1077.  * Beginning of area where the kernel should be able to handle a bus error
  1078.  * (which includes size errors) while in kernel mode.
  1079.  */
  1080. .globl    _MachProbeStart
  1081. _MachProbeStart:
  1082.  
  1083. /*
  1084.  * ----------------------------------------------------------------------
  1085.  *
  1086.  * Mach_Probe --
  1087.  *
  1088.  *    Read or write a virtual address handling bus errors that may occur.
  1089.  *    This routine is intended to be used to probe for memory-mapped devices.
  1090.  *
  1091.  *    Mach_Probe(byteCount, readAddress, writeAddress)
  1092.  *
  1093.  * Results:
  1094.  *    SUCCESS if the read or write worked and FAILURE otherwise.
  1095.  *
  1096.  * Side effects:
  1097.  *    None.
  1098.  *
  1099.  * ----------------------------------------------------------------------
  1100.  */
  1101. .globl    _Mach_Probe
  1102. _Mach_Probe:
  1103.                 /* %o0 = size in bytes of the read/write to do.
  1104.                  * Must be 1, 2, 4, or 8 bytes. */
  1105.                 /* %o1 = address to read. */
  1106.                 /* %o2 = Location to store the read value. */
  1107.     cmp    %o0, 1
  1108.     bne    Read2Bytes
  1109.     nop
  1110.     ldub    [%o1], %OUT_TEMP1
  1111.     stb    %OUT_TEMP1, [%o2]
  1112.     set    SUCCESS, %RETURN_VAL_REG
  1113.     retl
  1114.     nop
  1115. Read2Bytes:
  1116.     cmp    %o0, 2
  1117.     bne    Read4Bytes
  1118.     nop
  1119.     andcc    %o1, 0x1, %g0
  1120.     bne    BadRead
  1121.     nop
  1122.     andcc    %o2, 0x1, %g0
  1123.     bne    BadRead
  1124.     nop
  1125.     lduh    [%o1], %OUT_TEMP1
  1126.     sth    %OUT_TEMP1, [%o2]
  1127.     set    SUCCESS, %RETURN_VAL_REG
  1128.     retl
  1129.     nop
  1130. Read4Bytes:
  1131.     cmp    %o0, 4
  1132.     bne    Read8Bytes
  1133.     nop
  1134.     andcc    %o1, 0x3, %g0
  1135.     bne    BadRead
  1136.     nop
  1137.     andcc    %o2, 0x3, %g0
  1138.     bne    BadRead
  1139.     nop
  1140.     ld    [%o1], %OUT_TEMP1
  1141.     st    %OUT_TEMP1, [%o2]
  1142.     set    SUCCESS, %RETURN_VAL_REG
  1143.     retl
  1144.     nop
  1145. Read8Bytes:
  1146.     cmp    %o0, 8
  1147.     bne    BadRead
  1148.     nop
  1149.     andcc    %o1, 0x7, %g0
  1150.     bne    BadRead
  1151.     nop
  1152.     andcc    %o2, 0x7, %g0
  1153.     bne    BadRead
  1154.     nop
  1155.     ldd    [%o1], %OUT_TEMP1
  1156.     std    %OUT_TEMP1, [%o2]
  1157.     set    SUCCESS, %RETURN_VAL_REG
  1158.     retl
  1159.     nop
  1160. BadRead:
  1161.     set    FAILURE, %RETURN_VAL_REG
  1162.     retl
  1163.     nop
  1164.  
  1165. /*
  1166.  * End of the area where the kernel should be able to handle a bus error
  1167.  * while in kernel mode.
  1168.  */
  1169. .globl    _MachProbeEnd
  1170. _MachProbeEnd:
  1171.  
  1172. /*
  1173.  *---------------------------------------------------------------------
  1174.  *
  1175.  * MachHandleBadProbe -
  1176.  *
  1177.  *    A page fault occured during a probe operation, which means
  1178.  *    the page couldn't be paged in or there was a size error.  So we want to
  1179.  *    return FAILURE to the caller of the probe operation.  This means we must
  1180.  *    return this value from the routine doing the probe.
  1181.  *
  1182.  * Results:
  1183.  *    FAILURE returned to caller of probe operation.
  1184.  *
  1185.  * Side effects:
  1186.  *    We cause the routine that was doing the probe to return FAILURE.
  1187.  *
  1188.  *---------------------------------------------------------------------
  1189.  */
  1190. .globl    _MachHandleBadProbe
  1191. _MachHandleBadProbe:
  1192.     restore        /* back to page fault trap window */
  1193.     mov    %CUR_PSR_REG, %i1    /* get trap psr */
  1194.     restore        /* back to probe routine window */
  1195.     /* Mach_Probe is a leaf routine - return stuff in %o0 */
  1196.     set    FAILURE, %o0    /* return FAILURE */
  1197.     /* Set interrupts to what they were when trap occured. */
  1198.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1199.     retl        /* return from leaf routine */
  1200.     nop
  1201.  
  1202. /*
  1203.  *---------------------------------------------------------------------
  1204.  *
  1205.  * MachHandleBadQuickCopy -
  1206.  *
  1207.  *    A page fault occured during a quick copy operation, which isn't
  1208.  *    allowed.  So we want to return FAILURE to the caller of the copy
  1209.  *    operation.  This means we must return this value from the routine
  1210.  *    doing the copy.
  1211.  *
  1212.  * Results:
  1213.  *    FAILURE returned to caller of copy operation.
  1214.  *
  1215.  * Side effects:
  1216.  *    We cause the routine that was doing the copy to return FAILURE.
  1217.  *
  1218.  *---------------------------------------------------------------------
  1219.  */
  1220. .globl    _MachHandleBadQuickCopy
  1221. _MachHandleBadQuickCopy:
  1222.     restore        /* back to page fault trap window */
  1223.     mov    %CUR_PSR_REG, %i1    /* get trap psr */
  1224.     restore        /* back to copy routine window */
  1225.     /* VmMachQuickNDirtyCopy is NOT a leaf routine - return stuff in %i0 */
  1226.     set    FAILURE, %i0    /* return FAILURE */
  1227.     /* Set interrupts to what they were when trap occured. */
  1228.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1229.     ret        /* return from non-leaf routine */
  1230.     restore
  1231. /*
  1232.  *---------------------------------------------------------------------
  1233.  *
  1234.  * _MachFPULoadState -
  1235.  *
  1236.  *    Load the current state into the FPU.
  1237.  *
  1238.  *    void MachFPULoadState(regStatePtr)
  1239.  *          Mach_RegState *regStatePtr;
  1240.  * Results:
  1241.  *    None
  1242.  *
  1243.  * Side effects:
  1244.  *    FPU registers changed.
  1245.  *
  1246.  *---------------------------------------------------------------------
  1247.  */
  1248. .globl    _MachFPULoadState
  1249. _MachFPULoadState:
  1250.     /*
  1251.      * Insure that the FPU is enabled.
  1252.      */
  1253.     mov    %psr, %o1
  1254.     set    MACH_ENABLE_FPP, %o2
  1255.     or    %o2,%o1,%o2
  1256.     mov    %o2,%psr
  1257.     nop
  1258.     nop
  1259.     nop
  1260.     ld    [%o0 + MACH_FPU_FSR_OFFSET], %fsr
  1261.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*0],%f0
  1262.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*2],%f2 
  1263.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*4],%f4 
  1264.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*6],%f6 
  1265.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*8],%f8 
  1266.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*10],%f10
  1267.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*12],%f12
  1268.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*14],%f14 
  1269.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*16],%f16 
  1270.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*18],%f18 
  1271.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*20],%f20 
  1272.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*22],%f22
  1273.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*24],%f24 
  1274.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*26],%f26
  1275.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*28],%f28
  1276.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*30],%f30
  1277.     retl
  1278.     mov    %o1,%psr
  1279. /*
  1280.  *---------------------------------------------------------------------
  1281.  *
  1282.  * MachFPUDumpState -
  1283.  *
  1284.  *    Save the FPU state of a process into the Mach_RegState structure.
  1285.  *
  1286.  *    void MachFPUDumpState(regStatePtr)
  1287.  *        Mach_RegState *regStatePtr;
  1288.  *
  1289.  * Results:
  1290.  *    None
  1291.  *
  1292.  * Side effects:
  1293.  *    Pending exception state cleared from FPU.
  1294.  *
  1295.  *---------------------------------------------------------------------
  1296.  */
  1297. .globl    _MachFPUDumpState
  1298. _MachFPUDumpState:
  1299.     /*
  1300.      * Insure that the FPU is enabled.
  1301.      */
  1302.     mov    %psr, %o1
  1303.     set    MACH_ENABLE_FPP, %o2
  1304.     or    %o2,%o1,%o2
  1305.     mov    %o2,%psr
  1306.     /*
  1307.      * Next three instructions should not be FPU instructions. 
  1308.      */
  1309.     set     MACH_FSR_QUEUE_NOT_EMPTY, %o3
  1310.     add    %o0, MACH_FPU_QUEUE_OFFSET, %o4
  1311.     mov    0, %o5
  1312.  
  1313.     /*
  1314.      * We have to do the same trick here as in Mach_ContextSwitch,
  1315.      * flagging the instruction that waits for the FPU to finish
  1316.      * and checking for exceptions.  We have a different label this
  1317.      * time, of course.  The trap handler knows that if the trap
  1318.      * occurred at this label then we were already dumping the state
  1319.      * and it shouldn't call us recursively.
  1320.      * Note that the fsr is read again in the loop, and the purpose
  1321.      * of this extra read is to have a separate label for the first
  1322.      * read -- traps on subsequent reads of fsr would be an error.
  1323.      */
  1324. .global _machFPUDumpSyncInst
  1325. _machFPUDumpSyncInst: 
  1326.     st    %fsr, [%o0 + MACH_FPU_FSR_OFFSET]
  1327.         /*
  1328.      * The following symbol is include to make the following code 
  1329.      * be attributed to the routine MachFPUDumpState2 and not
  1330.      * _machFPUDumpSyncInst.
  1331.      */
  1332. .globl    MachFPUDumpState2
  1333. MachFPUDumpState2:
  1334.     /*
  1335.      * While MACH_FSR_QUEUE_NOT_EMPTY set in the FSR, save
  1336.      * the entry in the %fq register.
  1337.      */
  1338. clearQueueLoop:
  1339.     st    %fsr, [%o0 + MACH_FPU_FSR_OFFSET]
  1340.     ld      [%o0 + MACH_FPU_FSR_OFFSET], %o2
  1341.     andcc    %o2,%o3,%g0
  1342.     be    queueEmpty
  1343.     nop
  1344.     std    %fq, [%o4+%o5]
  1345.     ba    clearQueueLoop
  1346.     add    %o5,8,%o5
  1347. queueEmpty:
  1348.     /*
  1349.      * Compute numQueueEntries.
  1350.      */
  1351.     srl    %o5,3,%o5
  1352.     st    %o5, [%o0 + MACH_FPU_QUEUE_COUNT]
  1353.     /*
  1354.      * Save registers two at a time.
  1355.      */
  1356.     std    %f0, [%o0 + MACH_FPU_REGS_OFFSET+4*0]
  1357.     std    %f2, [%o0 + MACH_FPU_REGS_OFFSET+4*2]
  1358.     std    %f4, [%o0 + MACH_FPU_REGS_OFFSET+4*4]
  1359.     std    %f6, [%o0 + MACH_FPU_REGS_OFFSET+4*6]
  1360.     std    %f8, [%o0 + MACH_FPU_REGS_OFFSET+4*8]
  1361.     std    %f10, [%o0 + MACH_FPU_REGS_OFFSET+4*10]
  1362.     std    %f12, [%o0 + MACH_FPU_REGS_OFFSET+4*12]
  1363.     std    %f14, [%o0 + MACH_FPU_REGS_OFFSET+4*14]
  1364.     std    %f16, [%o0 + MACH_FPU_REGS_OFFSET+4*16]
  1365.     std    %f18, [%o0 + MACH_FPU_REGS_OFFSET+4*18]
  1366.     std    %f20, [%o0 + MACH_FPU_REGS_OFFSET+4*20]
  1367.     std    %f22, [%o0 + MACH_FPU_REGS_OFFSET+4*22]
  1368.     std    %f24, [%o0 + MACH_FPU_REGS_OFFSET+4*24]
  1369.     std    %f26, [%o0 + MACH_FPU_REGS_OFFSET+4*26]
  1370.     std    %f28, [%o0 + MACH_FPU_REGS_OFFSET+4*28]
  1371.     std    %f30, [%o0 + MACH_FPU_REGS_OFFSET+4*30]
  1372.     /*
  1373.      * Restore the FPU to previous state and return.
  1374.      */
  1375.     retl
  1376.     mov    %o1,%psr
  1377.  
  1378. /*
  1379.  * ----------------------------------------------------------------------
  1380.  *
  1381.  * Mach_Return2(val)  --
  1382.  *
  1383.  *    Set the second return value.
  1384.  *
  1385.  * Results:
  1386.  *    None.
  1387.  *
  1388.  * Side effects:
  1389.  *    i1 <- val.
  1390.  *
  1391.  * ----------------------------------------------------------------------
  1392.  */
  1393. .globl    _Mach_Return2
  1394. _Mach_Return2:
  1395.     retl
  1396.     mov    %o0, %i1
  1397.